package com.ltmonitor.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import com.ltmonitor.service.IGPSRealDataService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.entity.GpsInfo;
import com.ltmonitor.entity.Terminal;
import com.ltmonitor.entity.VehicleData;
import com.ltmonitor.service.IRealDataService;

public class RealDataServiceProxy implements IRealDataService {

	private static Logger logger = Logger.getLogger(RealDataServiceProxy.class);
	private int refreshInterval;

	private IRealDataService realDataServiceClient;
	
	private IRealDataService realDataServiceClient2;
	
	@Autowired
	private IGPSRealDataService gpsRealDataService;
		

	private boolean startUpdate = true;

	private ConcurrentMap<String, GPSRealData> realDataMap = new ConcurrentHashMap<String, GPSRealData>();
	//private WeakHashMap<String, GPSRealData> realDataMap = new WeakHashMap<String, GPSRealData>();
	/**
	 * 实时数据数据处理线程
	 */
	private Thread processRealDataThread;

	private boolean isConnected = false;

	public void start() {
		String hql = "from GPSRealData where  simNo is not null and plateNo is not null order by sendTime";
		List ls = this.gpsRealDataService.query(hql);
		for (Object obj : ls) {
			GPSRealData rd = (GPSRealData) obj;
			rd.setOnline(false);
			this.realDataMap.put(rd.getSimNo(), rd);
		}
		processRealDataThread = new Thread(new Runnable() {
			public void run() {
				ProcessRealDataThreadFunc();
			}
		});
		processRealDataThread.start();
	}

	@PreDestroy
	public void stop() {
		startUpdate = false;
		try {
			processRealDataThread.stop();
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
	}

	private void ProcessRealDataThreadFunc() {
		//
		while (startUpdate) {
			try {
				List<GPSRealData> onlineDatas = this.getOnlineRealDataList();
				for (GPSRealData rd : onlineDatas) {
					realDataMap.put(rd.getSimNo(), rd);
				}
				isConnected = true;
			} catch (Exception ex) {
				isConnected = false;
				logger.error(ex.getMessage(),ex);
			}
			try {
				Thread.sleep(this.refreshInterval);
			} catch (InterruptedException e1) {
				break;
			}

		}
	}

	@Override
	public void update(GPSRealData rd) {
		realDataServiceClient.update(rd);

	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	@Override
	public GPSRealData get(String simNo) {
		try {
			if (simNo == null)
				return null;
			if (realDataMap.containsKey(simNo)) {
				return realDataMap.get(simNo);
			} else if (isConnected) {
				//logger.error("proxy before get:" + simNo);
				GPSRealData rd = this.realDataServiceClient.get(simNo);
				//logger.error("proxy end get:" + simNo);
				if (rd != null)
					realDataMap.put(simNo, rd);
				else
					this.logger.error("找不到实时数据:" + simNo);
				return rd;
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(),ex);
		}
		return null;
	}

	@Override
	public List<GPSRealData> getRealDataList(List<String> simNoList) {
		return realDataServiceClient.getRealDataList(simNoList);
	}


	public void updateOnlineTime(GPSRealData rd, Date onlineDate) {
		//realDataServiceClient.updateOnlineTime(rd, onlineDate);

	}

	@Override
	public void stopService() {
		realDataServiceClient.stopService();

	}

	@Override
	public List<GPSRealData> getOnlineRealDataList() {
		List<GPSRealData> resultList = new ArrayList<GPSRealData>();
		Map<String, GPSRealData> tempMap = new HashMap<String, GPSRealData>();
		
		// 第一路，保存
		try {
			List<GPSRealData> list = realDataServiceClient.getOnlineRealDataList();
			if (list.size() > 0) {
				for(GPSRealData gd:list) {
					tempMap.put(gd.getSimNo(), gd);
				}
			}
//			System.out.println(" 第一路数据量：" + list.size());
		} catch (Exception e) {
			// TODO: handle exception
//			System.out.println("第一路不存在！");
//			e.printStackTrace();
		}
		
		
		
		// 第二路,查重
		try {
			List<GPSRealData> list2 = realDataServiceClient2.getOnlineRealDataList();
			if (list2.size() > 0) {
				for (GPSRealData gd : list2) {
					if (tempMap.containsKey(gd.getSimNo())) {
						// 包含，比对
						GPSRealData gd1 = tempMap.get(gd.getSimNo());
						if (gd.getUpdateDate().getTime() > gd1.getUpdateDate().getTime()) { // 当前车辆更新时间大于旧的更新时间
							tempMap.put(gd.getSimNo(), gd);
						}
					} else {
						// 不包含，直接插入
						tempMap.put(gd.getSimNo(), gd);
					}
				} // end for
				
			}
//			System.out.println(" 第二路数据量：" + list2.size());
		} catch (Exception e) {
			// TODO: handle exception
//			System.out.println("第二路不存在");
		}
		
		//遍历取出
		for(GPSRealData value :tempMap.values()) {
			resultList.add(value);
		}
		
		return resultList;
	}

	@Override
	public void saveHisGpsInfo(GpsInfo gi) {

	}

	@Override
	public VehicleData getVehicleData(String simNo) {
		return realDataServiceClient.getVehicleData(simNo);
	}

	@Override
	public void updateVehicleData(String simNo, VehicleData v) {
		realDataServiceClient.updateVehicleData(simNo, v);

	}

	@Override
	public void UpdateConnectedState(String simNo, Boolean isConnected) {
		realDataServiceClient.UpdateConnectedState(simNo, isConnected);

	}

	@Override
	public Boolean isConnected(String simNo) {
		return realDataServiceClient.isConnected(simNo);
	}

	@Override
	public Terminal getTerminalByTermNo(String termNo) {
		return realDataServiceClient.getTerminalByTermNo(termNo);
	}

	@Override
	public void updateTerminal(String termNo, Terminal t) {
		realDataServiceClient.updateTerminal(termNo,t);
	}

	@Override
	public VehicleData getVehicleByPlateNo(String plateNo) {
		return this.getVehicleByPlateNo(plateNo);
	}

	public int getRefreshInterval() {
		return refreshInterval;
	}

	public void setRefreshInterval(int refreshInterval) {
		this.refreshInterval = refreshInterval;
	}

	public IRealDataService getRealDataServiceClient() {
		return realDataServiceClient;
	}

	public void setRealDataServiceClient(IRealDataService realDataServiceClient) {
		this.realDataServiceClient = realDataServiceClient;
	}

	public IRealDataService getRealDataServiceClient2() {
		return realDataServiceClient2;
	}

	public void setRealDataServiceClient2(IRealDataService realDataServiceClient2) {
		this.realDataServiceClient2 = realDataServiceClient2;
	}

}
